package com.smartfit;

import java.util.ArrayList;

public class PatternFinder
{
	static final int QUEUE_SIZE = 20;
	
	// 패턴분석 임계값
	double m_fDiffThreshold;
	int m_iStayState;
	
	// 현재 패턴
	public int m_iCurrentPattern;
	
	// 패턴 큐
	private int m_iStartIndex;
	private int m_iEndIndex;
	private int [] m_piQueue;
	
	protected class InflectionInfo
	{
		// 변곡점
		private ArrayList<Double> m_InflectionPoints;
		private double m_fMinValue;
		private double m_fMaxValue;
		
		
		public InflectionInfo()
		{
			m_InflectionPoints = new ArrayList<Double>();
			
			Clear();
		}
		
		public void Clear()
		{
			m_fMinValue = Double.MAX_VALUE;
			m_fMaxValue = Double.MIN_VALUE;
			
			m_InflectionPoints.clear();
		}
		
		public void Insert( double fPoint )
		{
			if ( m_fMinValue > fPoint )
			{
				m_fMinValue = fPoint;
			}
			
			if ( m_fMaxValue < fPoint )
			{
				m_fMaxValue = fPoint;
			}
			
			m_InflectionPoints.add( fPoint );
		}
		
		public boolean IsEmptyInflectionPoint()
		{
			if ( m_InflectionPoints.isEmpty() )
			{
				return true;
			}
			
			return false;
		}

		public double GetMinInflectionPoint()
		{
			if ( m_InflectionPoints.isEmpty() )
			{
				return Double.MAX_VALUE;
			}

			return m_fMinValue;
		}

		public double GetMaxInflectionPoint()
		{
			if ( m_InflectionPoints.isEmpty() )
			{
				return Double.MIN_VALUE;
			}
			
			return m_fMaxValue;
		}
	}
	
	// 변곡점(U/D)
	InflectionInfo [] m_pInflectionInfos;
	
	// constructor
	public PatternFinder()
	{
		m_piQueue = new int[QUEUE_SIZE];
		
		// 변곡점(U/D)
		m_pInflectionInfos = new InflectionInfo[2];
		
		for ( int i = 0 ; i < 2 ; i++ )
		{
			m_pInflectionInfos[i] = new InflectionInfo();
		}

		Clear();
	}
	
	// clear
	public void Clear()
	{
		m_iStayState = 0;
		
		m_iStartIndex = 0;
		m_iEndIndex = 0;
		
		for ( int i = 0 ; i < QUEUE_SIZE ; i++ )
		{
			m_piQueue[i] = AccelValueFileData.PATTERN_STAY;
		}
	}
	
	// 패턴분석 임계값 설정
	public void SetDiffThreshold( double fThreshold )
	{
		m_fDiffThreshold = fThreshold;
	}
	
	// insert
	public void Analyze( int iPattern , double fPoint )
	{
		double fDiffThreshold = m_fDiffThreshold;
		
		int iPreviosPattern = m_piQueue[m_iEndIndex];
		int iCurrentPattern = iPattern;
		
		if ( iPreviosPattern != iCurrentPattern )
		{
			m_pInflectionInfos[iCurrentPattern].Insert( fPoint ); 
		}
		//else
		{
			boolean bIsFixed = false;
			
			switch ( iCurrentPattern )
			{
				case AccelValueFileData.PATTERN_UP:
			
					if ( m_pInflectionInfos[iCurrentPattern].IsEmptyInflectionPoint() == false )
					{
						double fValue = m_pInflectionInfos[iCurrentPattern].GetMinInflectionPoint();
						double fDiff = Math.abs( fPoint - fValue );
						
						if ( fDiffThreshold < fDiff )
						{
							bIsFixed = true;
							Insert( iPattern );
						}
					}
					
					break;
					
				case AccelValueFileData.PATTERN_DOWN:
					
					if ( m_pInflectionInfos[iCurrentPattern].IsEmptyInflectionPoint() == false )
					{
						double fValue = m_pInflectionInfos[iCurrentPattern].GetMaxInflectionPoint();
						double fDiff = Math.abs( fPoint - fValue );
						
						if ( fDiffThreshold < fDiff )
						{
							bIsFixed = true;
							Insert( iPattern );
						}
					}

					break;
					
				default:
					
					return;
			}
			
			if ( bIsFixed )
			{
				m_pInflectionInfos[AccelValueFileData.PATTERN_UP].Clear();
				m_pInflectionInfos[AccelValueFileData.PATTERN_DOWN].Clear();
			}
			else
			{
				m_iStayState++;

//				if ( ( m_iStayState > 20 ) && ( iPreviosPattern != AccelValueFileData.PATTERN_STAY ) )
				if ( m_iStayState > 20 ) 
				{
					Insert( AccelValueFileData.PATTERN_STAY );
				}
			}
		}
	}
	
	public void Insert( int iPattern )
	{
		if ( m_iCurrentPattern == AccelValueFileData.PATTERN_STAY )
		{
			int iPreviousPatternIndex = ( ( m_iEndIndex - 1 ) % QUEUE_SIZE );
			
			if ( m_piQueue[iPreviousPatternIndex] == iPattern )
			{
				return;
			}
		}
		
		int iCurrentPatternIndex = ( ( m_iEndIndex + 1 ) % QUEUE_SIZE );
		
		if ( m_iStartIndex == iCurrentPatternIndex )
		{
			m_iStartIndex = ( ( m_iStartIndex + 1 ) % QUEUE_SIZE );
		}
		
		m_iEndIndex = iCurrentPatternIndex;
		
		m_iCurrentPattern = iPattern;
		m_piQueue[iCurrentPatternIndex] = iPattern;
	}
	
	public int GetCurrentPattern()
	{
		return m_iCurrentPattern;
	}
	
	public int GetStartIndex()
	{
		return m_iStartIndex;
	}
	
	public int GetEndIndex()
	{
		return m_iEndIndex;
	}
	
	public int [] GetQueue()
	{
		return m_piQueue;
	}
}